home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
ulib
/
fixdir.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
4KB
|
184 lines
/***********************************************************************
* $Id: fixdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $
*
*. Copyright(c) 1993,1994 by T.C. Zhao
* All rights reserved.
*.
*
* Given a directory name, expand it to absolute path.
* Or do the reverse.
*
***********************************************************************/
#if !defined(lint) && defined(F_ID)
char *id_fixdir = "$Id: fixdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $";
#endif
#include <stdio.h>
#include <string.h>
#include "unistd.h"
#include <pwd.h>
#include "ulib.h"
/************************************************************
* fix the tail of an expanded directory
***********************************************************/
char *
fix_dir_tail(char dir[])
{
return (dir[strlen(dir) - 1] != '/') ? strcat(dir, "/") : dir;
}
/*
* add one component to a dirname
*/
static void
add_one(char dir[], char one[])
{
char *q;
if (one[0] == '.' && one[1] == '.' && one[2] == '\0')
{
if ((q = strrchr(dir, '/')) && q != dir)
*q = '\0';
}
else if (one[0] == '~')
{
if (one[1] == '\0')
{ /* must be ~/ ... */
strcat(dir, (q = getenv("HOME")) ? q : "/");
}
else
{ /* must be ~name */
struct passwd *p = getpwnam(one + 1);
strcat(dir, p ? p->pw_dir : "/");
endpwent();
}
}
else if (!(one[0] == '.' && one[1] == '\0'))
{
strcat(strcat(dir, "/"), one);
}
}
/**************************************************************
* complete a dirname. If dir is NULL, return the local copy.
* ugly, but works for ./../../foo/./../ etc.
**************************************************************/
char *
fix_dirname(char dir[])
{
static char ldir[PATH_MAX], one[PATH_MAX];
char *p = ldir, *q = one;
if (!dir || !*dir)
return getcwd(dir ? dir : ldir, PATH_MAX - 2);
strcpy(ldir, dir);
if (ldir[0] != '/' && ldir[0] != '~')
getcwd(dir, PATH_MAX - 2);
else
dir[0] = '\0';
while (*p)
{
if (*p == '/')
{
*q = '\0';
if (q > one)
add_one(dir, (q = one));
}
else
*q++ = *p;
p++;
}
*q = '\0';
if (q > one)
add_one(dir, one);
return dir;
}
/*****************************************************************
* Search str for pat, and if found, replace it with rep
****************************************************************/
static void
pat_replace(char str[], const char *pat, const char *rep)
{
char *t;
char *d;
if (!(t = strstr(str, pat)))
return;
d = strdup(t + strlen(pat));
*t = '\0';
strcat(str, rep);
strcat(str, d);
free(d);
}
/******************************************************************
* Contract dirname from /usr/people/xxx to ~/ to save some length.
* Also replace the middle part of a path with X if the path is longer
* than limit. Useful when indicator is of limited length
******************************************************************/
const char *
contract_dirname(const char *dir, int limit)
{
static char buf[PATH_MAX];
const char *home = getenv("HOME");
char top[100];
char *t;
int l = strlen(dir);
limit = Max(18, limit);
if (l < limit || !home)
return dir;
strcpy(buf, dir);
pat_replace(buf, home, "~");
/* replace middle components with ... */
if ((l = strlen(buf)) > limit)
{
int k = limit / 3 - 2;
char *p = strchr(buf + k, '/');
char *q;
int i = 0;
q = buf + l - k;
while (*--q != '/')
;
if (q > p + 3)
{
/* replace whatever in between with X */
*++p = 'X';
*++p = 'X';
*++p = '\0';
strcpy(p, q);
}
}
return buf;
}
#ifdef TEST
main(int argc, char *argv[])
{
char pp[2048];
while (gets(pp))
{
fprintf(stderr, "%s=>", pp);
fprintf(stderr, "FIX: %s\n", fix_dirname(pp));
fprintf(stderr, "CON: %s\n", contract_dirname(pp, 30));
}
}
#endif